package com.citybox.shared.interceptor;


import cn.hutool.http.HtmlUtil;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;

@Slf4j
public class XssHttpServletRequestWraper extends HttpServletRequestWrapper {


    public XssHttpServletRequestWraper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (StringUtils.isEmpty(value)) {
            return value;
        }
        // 过滤html标记
        return HtmlUtil.filter(value);
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (StringUtils.isEmpty(value)) {
            return value;
        }
        // 过滤html标记
        return  HtmlUtil.filter(value);
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if(values == null) {
            return null;
        }
        for (int i = 0; i < values.length; i++) {
            if (StringUtils.isEmpty(values[i])) {
                values[i] = values[i];
            } else {
                // 过滤html标记
                values[i] = HtmlUtil.filter(values[i]);
            }
        }
        return values;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 请求方法为POST时会触发这个方法
        return getInputStreamWithXSSFilter();
    }


    public ServletInputStream getInputStreamWithXSSFilter() throws IOException {
        // 1. 读取请求体内容
        String requestBody = readRequestBody(super.getInputStream());

        // 2. 执行XSS过滤
        String filteredBody = filterXss(requestBody);

        // 3. 返回过滤后的输入流
        return createFilteredInputStream(filteredBody);
    }

    /**
     * 安全读取请求体
     */
    private String readRequestBody(InputStream inputStream) throws IOException {
        try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
             BufferedReader bufferedReader = new BufferedReader(reader)) {

            StringBuilder body = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                body.append(line);
            }
            return body.toString();
        }
    }

    /**
     * 执行XSS过滤
     */
    private String filterXss(String content) {
        // 使用Hutool过滤HTML
        String filtered = HtmlUtil.filter(content);
        // 恢复双引号
        return filtered.replace("&quot;", "\"");
    }

    /**
     * 创建过滤后的输入流
     */
    private ServletInputStream createFilteredInputStream(String content) {
        ByteArrayInputStream bais = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));

        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public boolean isFinished() {
                return bais.available() == 0;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener listener) {
                throw new UnsupportedOperationException("不支持异步读取");
            }
        };
    }
}
